package com.mac.macjetpackdemo.util

import android.graphics.Bitmap
import android.graphics.Canvas
import android.media.ThumbnailUtils
import android.util.Log
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.MultiFormatWriter
import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.journeyapps.barcodescanner.BarcodeEncoder

object QrCodeUtils {
    private const val TAG = "QrCodeUtils"

    fun createQrCode(str: String): Bitmap? {
        var bitmap: Bitmap? = null
        try {
            val formatWriter = MultiFormatWriter()
            val hints = mutableMapOf<EncodeHintType, Any>()
            hints[EncodeHintType.CHARACTER_SET] = "UTF-8"
            hints[EncodeHintType.MARGIN] = 0
            hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.H
            var matrix = formatWriter.encode(str, BarcodeFormat.QR_CODE, 200, 200, hints)
            matrix = deleteWhite(matrix)
            val barcodeEncoder = BarcodeEncoder()
            bitmap = barcodeEncoder.createBitmap(matrix)
        } catch (e: WriterException) {
            Log.d(TAG, "createQrCode: ${e.message}")
        } catch (e: IllegalArgumentException) {
            Log.d(TAG, "createQrCode: ${e.message}")
        }
        return bitmap
    }

    fun addLogo(bgBitmap: Bitmap, logoBitmap: Bitmap): Bitmap {
        val bgWidth = bgBitmap.width
        val bgHeight = bgBitmap.height
        val logoBitmapThumb =
            if (bgWidth / logoBitmap.width < 4 || bgHeight / logoBitmap.height < 4) {
                ThumbnailUtils.extractThumbnail(logoBitmap, bgWidth / 4, bgHeight / 4)
            } else {
                logoBitmap
            }
        val logoWidth = logoBitmapThumb.width
        val logoHeight = logoBitmapThumb.height
        val cvBitmap = Bitmap.createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888)
        Canvas(cvBitmap).run {
            drawBitmap(bgBitmap, 0f, 0f, null)
            drawBitmap(
                logoBitmapThumb, (bgWidth - logoWidth) / 2f, (bgHeight - logoHeight) / 2f,
                null
            )
            save()
            restore()
        }
        if (cvBitmap.isRecycled) {
            cvBitmap.recycle()
        }
        return cvBitmap
    }

    private fun deleteWhite(bitMatrix: BitMatrix): BitMatrix {
        val rec = bitMatrix.enclosingRectangle
        val resWidth = rec[2] + 1
        val resHeight = rec[3] + 1
        val newBitMatrix = BitMatrix(resWidth, resHeight)
        newBitMatrix.clear()
        for (i in 0 until resWidth) {
            for (j in 0 until resHeight) {
                if (bitMatrix.get(i + rec[0], j + rec[1])) {
                    newBitMatrix.set(i, j)
                }
            }
        }
        return newBitMatrix
    }
}